﻿/***************************************************
//  Copyright (c) Premium Tax Free 2011
***************************************************/

using System;
using System.Diagnostics;
using System.Drawing;

namespace PremierTaxFree.PTFLib.Extensions
{
    public static class DrawingEx
    {
        public static Point[] ToPoints(this Rectangle r)
        {
            return new Point[] { 
                r.Location, 
                new Point(r.X + r.Width, r.Y), 
                new Point(r.X + r.Width, r.Y + r.Height), 
                new Point(r.X, r.Y + r.Height)};
        }

        public static Point Invert(this Point point)
        {
            return new Point(-point.X, -point.Y);
        }

        public static float LengthTo(this Point from, Point to)
        {
            float result = Convert.ToSingle(Math.Sqrt((from.X - to.X) ^ 2 + (from.Y - to.Y) ^ 2));
            if (float.IsNaN(result))
                return 0;
            return result;
        }

        public static float ToAngle(this PointF p1, PointF p2)
        {
            return Convert.ToSingle(Math.Atan((p1.Y - p2.Y) / (p1.X - p2.X)));
        }

        public static PointF Cast(this Point point)
        {
            return new PointF(point.X, point.Y);
        }

        private static Random ms_Rnd = new Random(DateTime.Now.Millisecond);

        public static Point Random(this Point p, int min, int max)
        {
            int x = ms_Rnd.Next(min, max);
            int y = ms_Rnd.Next(min, max);
            return new Point(x, y);
        }

        public static Color Random(this Color color)
        {
            return Color.FromKnownColor((KnownColor)ms_Rnd.Next(1, 150));
        }

        public static Rectangle InflateEx(this Rectangle rect, int width = 20, int height = 20)
        {
            Rectangle r = rect;
            r.Inflate(width, height);
            return r;
        }

        public static PointF Rotate(this PointF center, SizeF radius, double angle)
        {
            float x = Convert.ToSingle(center.X + (radius.Width * Math.Cos(angle)));
            float y = Convert.ToSingle(center.Y + (radius.Height * Math.Sin(angle)));
            return new PointF(x, y);
        }

        public static PointF Rotate(this PointF center, PointF point, float angle)
        {
            float w = point.X - center.X;
            float h = point.Y - center.Y;
            double r = Math.Sqrt(w * w + h * h);
            double value = Math.Atan(h / w) + angle;
            Debug.WriteLine(value, " value ");
            return new PointF(
                Convert.ToSingle(center.X + (r * Math.Cos(value))),
                Convert.ToSingle(center.Y + (r * Math.Sin(value))));
        }

        public static PointF Center(this Rectangle rect)
        {
            return new PointF(rect.X + rect.Width / 2.0f, rect.Y + rect.Height / 2.0f);
        }

        public static Rectangle Bounds(this Rectangle rect, float angle)
        {
            PointF p0 = new PointF(rect.X + rect.Width / 2.0f, rect.Y + rect.Height / 2.0f);
            PointF p1 = p0.Rotate(new PointF(rect.Left, rect.Top), angle);
            PointF p2 = p0.Rotate(new PointF(rect.Right, rect.Top), angle);
            PointF p3 = p0.Rotate(new PointF(rect.Right, rect.Bottom), angle);
            PointF p4 = p0.Rotate(new PointF(rect.Left, rect.Bottom), angle);
            return Bounds(p1, p2, p3, p4);
        }

        public static Rectangle Bounds(params PointF[] points)
        {
            const int MIN = 10;
            float x1 = float.MaxValue;
            float x2 = float.MinValue;
            float y1 = float.MaxValue;
            float y2 = float.MinValue;

            foreach (PointF p in points)
            {
                if (x1 > p.X)
                    x1 = p.X;
                if (x2 < p.X)
                    x2 = p.X;
                if (y1 > p.Y)
                    y1 = p.Y;
                if (y2 < p.Y)
                    y2 = p.Y;
            }

            return
                Rectangle.Ceiling(RectangleF.FromLTRB(x1, y1, (x1 == x2) ? x1 + MIN : x2, (y1 == y2) ? y2 + MIN : y2));
        }

        public static Rectangle Area(this Rectangle r1, Rectangle r2)
        {
            return Rectangle.FromLTRB(Math.Min(r1.Left, r2.Left), Math.Min(r1.Top, r2.Top),
                Math.Max(r1.Right, r2.Right), Math.Max(r1.Bottom, r2.Bottom));
        }

        public static Rectangle Invalid(this Rectangle r)
        {
            return Rectangle.FromLTRB(int.MaxValue, int.MaxValue, int.MinValue, int.MinValue);
        }
    }
}
